package com.ustc.hewei.rpc.client.net.impl;

import com.ustc.hewei.rpc.client.net.NetClient;
import com.ustc.hewei.rpc.client.net.SendHandler;
import com.ustc.hewei.rpc.common.protocol.Service;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;

/**
* @description: 客户端的服务连接和数据收发
* @author hewei
* @date 2022/7/28 20:14
* @version 1.0
*/

@Slf4j
public class NettyRpcClient implements NetClient {

    /*
     * @description: 向服务端发送请求，返回方法调用的结果
     * @param data requestWarp对象的序列化数组
     * @param service 里面保存着对应服务器的地址以及端口号
     * @return byte[] 返回的响应信息
     * @author: hewei
     * @date: 2022/7/29 20:12
     **/
    @Override
    public byte[] sendRequest(byte[] data, Service service) {
        SendHandler sendHandler = new SendHandler(data);
        byte[] response;

        //将地址进行分割，因为形式是"ip：port"
        String[] split = service.getAddress().split(":");
        int port = Integer.parseInt(split[1]);
        String ip = split[0];
        NioEventLoopGroup group = new NioEventLoopGroup();
        try {
            new Bootstrap().group(group).channel(NioSocketChannel.class)
                    .option(ChannelOption.TCP_NODELAY, true)
                    .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 1000)
                    //设置可以接收的大小，默认为2048个字节，不够用
                    //.option(ChannelOption.RCVBUF_ALLOCATOR, new FixedRecvByteBufAllocator(20480))
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            //调用自定义的消息处理器
                            socketChannel.pipeline().addLast(sendHandler);
                        }
                    }).connect(ip, port).sync();
            response = (byte[]) sendHandler.getResponse();
            log.info("客户端从 {} 接收响应成功！ {}", service.getAddress(), response);
        } catch (InterruptedException e) {
            throw new RuntimeException("客户端网络连接异常！", e);
        } finally {
            group.shutdownGracefully(0, 0, TimeUnit.MILLISECONDS);
        }
        return response;
    }
}
